package taskexecutor

import (
	"encoding/json"
	"fmt"
	"log"
	"main/general"
	"main/handlers"
	"sync"
	"time"
)

var cache = struct {
	sync.RWMutex
	data map[int64]string // 缓存 task.ID 和 alarmStatus 的映射
}{data: make(map[int64]string)}

// ExecuteTask 执行任务组，并减少多次连接
func (te *TaskExecutor) ExecuteTask(tasks []Task) {
	if len(tasks) == 0 {
		log.Println("任务列表为空")
		return
	}

	// 根据第一条任务的 AlarmConfigGroupCode 判断任务类型
	taskType := tasks[0].AlarmConfigGroupCode
	switch taskType {
	case "http_status":
		handleHTTPTasks(tasks)
	case "k8s_api":
		handleK8STasks(tasks)
	case "http_api_prometheus":
		handlePrometheusTasks(tasks)
	default:
		log.Printf("未知任务组类型: %s\n", taskType)
	}
}

func handlePrometheusTasks(PrometheusTasks []Task) {
	for _, task := range PrometheusTasks {
		var data general.PrometheusData

		response, err := general.QueryPrometheus(task.AlarmConfigGroupUrl, task.AlarmConfigFormula)
		if err != nil {
			log.Printf("Prometheus API查询失败，ID: %d，错误: %v\n", task.ID, err)
			continue
		}

		if task.AlarmConfigAction == "promql.uniquevalue" {

			prometheusDataList, err := general.ProcessPrometheusData(response)
			if err != nil {
				log.Printf("Prometheus API数据格式转换失败，ID: %d，错误: %v\n", task.ID, err)
				continue
			}

			// 检查结果数量
			if len(prometheusDataList) != 1 {
				log.Printf("Prometheus API返回多条或无结果，ID: %d，结果数量: %d\n", task.ID, len(prometheusDataList))
				continue
			}

			// 取第一个（唯一）结果
			data = prometheusDataList[0]
		}

		// 将 Metric 转为 JSON 字符串
		metricStr, err := json.Marshal(data.Metric)
		if err != nil {
			log.Printf("Metric 转换为字符串失败，ID: %d，错误: %v\n", task.ID, err)
			continue
		}

		log.Printf("Prometheus API任务成功，访问: %s, 指标值: %v, 时间: %s, Metric: %s\n",
			task.AlarmConfigGroupUrl, data.Value, data.Time, string(metricStr))

		// 插入任务执行结果到数据库
		insertTaskResult(task, string(metricStr), data.Time, data.Value, 1)
	}
}

// handleHTTPTasks 处理 HTTP 类型的任务
func handleHTTPTasks(httpTasks []Task) {
	for _, task := range httpTasks {
		if task.AlarmConfigAction == "http.status" {
			urlData, urlStatus, err := general.FetchURL(task.AlarmConfigGroupUrl)
			if err != nil {
				log.Printf("HTTP 任务失败，ID: %d，错误: %v\n", task.ID, err)
				continue
			}

			log.Printf("HTTP 任务成功，访问: %s, 返回数据: %s, 状态: %s\n", task.AlarmConfigGroupUrl, urlData, urlStatus)

			// 插入任务执行结果到数据库
			insertTaskResult(task, urlData, time.Now(), urlStatus, 1)
		}
	}
}

func handleK8STasks(k8sTasks []Task) {
	// 转换任务为 TaskInfo 列表
	taskInfos := []general.TaskInfo{}
	for _, task := range k8sTasks {
		nameSpace, controllerName, controllerType, err := general.K8sApptypeCutting(task.AlarmConfigFormula)
		if err != nil {
			log.Printf("K8S 任务批量处理,不支持的alarm_config_formula格式: %v\n", err)
			return
		}

		taskInfos = append(taskInfos, general.TaskInfo{
			TaskID:         task.AlarmConfigName,
			ControllerName: controllerName,
			Namespace:      nameSpace,
			ControllerType: controllerType,
		})
	}

	// 执行 K8S 类型任务
	var results map[string]general.AlarmEventResult
	var err error

	if k8sTasks[0].AlarmConfigAction == "pod.status" {
		results, err = general.FetchPodStatuses(k8sTasks[0].AlarmConfigGroupToken, taskInfos)
		if err != nil {
			log.Printf("K8S 任务批量处理失败: %v\n", err)
			return
		}
	}

	// 处理返回结果并插入任务执行结果
	for _, task := range k8sTasks {
		if task.AlarmConfigAction == "pod.status" {
			resultValue := results[task.AlarmConfigName]
			if resultValue.Error != nil {
				log.Printf("K8S 任务失败，ID: %d，错误: %v\n", task.ID, resultValue.Error)
				continue
			}

			log.Printf("K8S 任务成功，ID: %d，健康状态: %s，值: %s\n", task.ID, resultValue.Result, resultValue.ResultStatus)

			// 插入任务执行结果到数据库
			insertTaskResult(task, resultValue.Result, resultValue.ResultTime, resultValue.ResultStatus, 1)
		}
	}
}

// insertTaskResult 插入任务执行结果到数据库
func insertTaskResult(task Task, result string, resultTime, resultStatus interface{}, execStatus int) error {
	// 格式化结果状态值
	valueStr := fmt.Sprintf("%v", resultStatus)
	alarmStatus, err := general.ComparatorOutRange(valueStr, task.AlarmCorrectValue, task.AlarmJudgmentFormula)
	if err != nil {
		log.Printf("任务告警值比较失败，ID: %d，错误: %v\n", task.ID, err)
		return err
	}

	// 如果结果长度大于1000字符，限制为固定长度
	if len(result) > 1000 {
		result = "返回信息大于1000字符,不做有效记录"
	}

	// 使用锁来保护缓存的读写
	cache.RLock()
	cachedAlarmStatus, exists := cache.data[task.ID]
	cache.RUnlock()

	// 如果缓存中没有对应的task.ID 或者 alarmStatus发生变化，才执行插入操作
	if !exists || cachedAlarmStatus != alarmStatus {
		// 插入数据库
		query := "INSERT INTO alarm_event (`alarm_config_id`, `alarm_event_result`, `alarm_event_result_time`, `alarm_event_result_status`, `alarm_event_exec_status`, `alarm_event_alarm_status`) VALUES (?, ?, ?, ?, ?, ?);"
		_, err = handlers.ExecuteNonQuery(query, task.ID, result, resultTime, resultStatus, execStatus, alarmStatus)
		if err != nil {
			log.Printf("任务结果插入数据库失败，ID: %d，错误: %v\n", task.ID, err)
		} else {
			// 更新缓存
			cache.Lock()
			cache.data[task.ID] = alarmStatus
			cache.Unlock()
		}
	} else {
		log.Printf("任务,ID: %d,状态:%v,没有发生改变:,不执行插入数据库动作\n", task.ID, alarmStatus)
	}
	return err
}
